/******************************************************************************\
*                                                                              *
 *     File: Dierentuin_cc                                                      *
 *                                                                              *
 *   Author: Jan Meuleman / Douwe A. van Twillert                               *
 *  Purpose: de definitie (implementatie) van de klasse Dierentuin              *
 *  Version: 1.0      MEM 20020124                                              *
 *           - eerste versie                                                    *
 *  Version: 1.1      TWI 20080218                                              *
 *           - header aangepast voor duidelijk kunnen printen                   *
 *           - kleine aanpassingen om het half werkend te krijgen               *
 *                                                                              *
 \******************************************************************************/

#include "Dierentuin.h"
#include "assert.h"
#include <map>
#include <iostream>
#include <stdio.h>
using namespace std;

/*
 *   Constructor
 */
Dierentuin::Dierentuin() {
	de_naam = "Artis";

	dieren = new map<int, Dier*> ;
	beschikbareDierNummers = new vector<int> ;
	hoogsteDierNummer = 0;

	BOND = Singleton::instance();
	kooien_admin = KooiAdmin::instance();

	description = "Dierentuin Administration";
	menufunctions = new vector<Menufunction *>();
	menufunctions->push_back(new Menufunction("Dier toevoegen",					(adminfunction) &Dierentuin::dierToevoegen));
	menufunctions->push_back(new Menufunction("Dier verwijderen",				(adminfunction) &Dierentuin::dierVerwijderen));
	menufunctions->push_back(new Menufunction("Huidige dierenlijst printen",	(adminfunction) &Dierentuin::overzichtDieren));
	menufunctions->push_back(new Menufunction("Werknemer toevoegen",			(adminfunction) &Dierentuin::werknemerToevoegen));
	menufunctions->push_back(new Menufunction("Werknemer verwijderen",			(adminfunction) &Dierentuin::werknemerVerwijderen));
	menufunctions->push_back(new Menufunction("Huidige werknemerslijst printen",(adminfunction) &Dierentuin::overzichtWerknemers));
	menufunctions->push_back(new Menufunction("Huidige salarispost printen",	(adminfunction) &Dierentuin::getSalarisPost));
}
/*
 *   Destructor
 */
Dierentuin::~Dierentuin() {
	de_naam = "";
	//hoogsteWerknemerNummer = 0;
	hoogsteDierNummer = 0;

	beschikbareDierNummers->erase(beschikbareDierNummers->begin(), beschikbareDierNummers->end());
	delete beschikbareDierNummers;

//	beschikbareWerknemerNummers->erase(beschikbareWerknemerNummers->begin(), beschikbareWerknemerNummers->end());
//	delete beschikbareWerknemerNummers;
	//door de lijst heen loopen en alle dieren verwijderen
	//hierdoor blijven er geen waarden meer achter in het geheugen.

	//	//dieren algemene lijst leeg gooien
	for (map<int, Dier *>::iterator iter = dieren->begin(); iter != dieren->end(); ++iter) {
		delete iter->second;
	}
	delete dieren;
	//
	delete BOND;

	delete kooien_admin;

}

/*
 *   Dierentuin::getNaam()
 */
string Dierentuin::getNaam() {
	return de_naam;
}

map<int, Dier*>* Dierentuin::getDieren() {
	return dieren;
}


void Dierentuin::dierToevoegen() {
		assert(kooien_admin->getKooien() != 0);
		Dier* nieuwDier = new Dier();

	// als het dier aan de algemene lijst wordt toegevoegd gebeurt diet met een int en de pointer na het dier.
	//eerst wordt er gekeken of er beschikbare nummers zijn, en worden die gebruikt, en anders
	//wordt de int van het hoogsteDierNummer gebruikt.
	//als een dier verwijderd wordt, dan wordt zijn nummer beschikbaar en kan die hier gebruikt worden
	if (beschikbareDierNummers->size() > 0) {
		vector<int>::iterator iter = beschikbareDierNummers->begin();

		cout << (*iter) << " deze is beschikbaar" << endl;

		dieren -> insert(make_pair((*iter), nieuwDier));

		beschikbareDierNummers->erase(iter);

		cout << "Dier " << nieuwDier->getNaam() << " toegevoegd met nummer: " << (*iter) << endl;

	} else {
		dieren -> insert(make_pair(hoogsteDierNummer, nieuwDier));
		cout << "Dier " << nieuwDier->getNaam() << " toegevoegd met nummer: " << hoogsteDierNummer << endl;
	}
	hoogsteDierNummer++;

	//kooi opzoeken waar het dier in gezet moet worden, als die nog niet bestaat, deze aanmaken

	map<string, Kooi*>::iterator it = kooien_admin->getKooien()->find(nieuwDier->getSoort());

	if (it == kooien_admin->getKooien()->end()) {
		cout << "nieuwe kooi nodig" << endl;

		Kooi *kooi = new Kooi(nieuwDier->getSoort());

		kooi->addDier(nieuwDier);

		kooien_admin->getKooien()->insert(pair<string, Kooi*> (nieuwDier->getSoort(), kooi));

	} else {
		it->second->addDier(nieuwDier);
	}

}



/*
 *   Dierentuin::dierVerwijderen()
 */
void Dierentuin::dierVerwijderen() {
	cout << endl << "Geef op een regel, gescheiden door spatie(s) het"
		" dierSoort dierNummer op dat verwijderd moet worden." << endl;

	string dierSoort;
	int dierNR;

	cin >> dierSoort >> dierNR;

	map<string, Kooi*>::iterator kooiIter = kooien_admin->getKooien()->find(dierSoort);

	if (kooiIter->first == dierSoort) {
		map<int, Dier*>::iterator iter = dieren->find(dierNR);

		if (iter == dieren->end()) {
			cout << "het lieve diertje met nummer " << dierNR << "is niet gevonden" << endl;
		} else {
			dierVerwijderen(dierNR, dierSoort);

			cout << "Dier met nummer: " << dierNR << " is verwijderd" << endl;
		}
		cout << "done " << endl;
	} else {
		cout << "de kooi met het opgeven diersoort kan niet gevonden worden " << dierSoort << endl;
	}
}

void Dierentuin::dierVerwijderen(int dierNR, string dierSoort) {
	assert(dierSoort != "");

	map<string, Kooi*>::iterator kooiIter = kooien_admin->getKooien()->find(dierSoort);
	map<int, Dier*>::iterator iter = dieren->find(dierNR);

	Dier* teVerwijderenDier = iter->second;

	dieren->erase(dierNR);
	kooiIter->second->dierVerwijderen(iter->second);

	beschikbareDierNummers->push_back(dierNR);

	delete teVerwijderenDier;

}

/*
 *   Dierentuin::werknemerToevoegen()
 */
void Dierentuin::werknemerToevoegen() {
	p2f = &WerknemerAdmin::werknemerToevoegen;

	(objWA.*p2f)();
	cout << "ik ben een werknemer en ben toegevoegd" << endl;

}

/*
 *   Dierentuin::werknemerVerwijderen()
 */
void Dierentuin::werknemerVerwijderen() {
	p2f = &WerknemerAdmin::werknemerVerwijderen;

	(objWA.*p2f)();

}
/*
 *   Dierentuin::overzichtWerknemers()
 */
void Dierentuin::overzichtWerknemers() {
	p2f = &WerknemerAdmin::toonAlleWerknemers;

	(objWA.*p2f)();
}


/*
 *   Dierentuin::overzichtDieren()
 */
void Dierentuin::overzichtDieren() {
	cout << "Overzicht van alle dieren" << endl;

	// itereer over alle dieren uit de lijst van dieren
	for (map<int, Dier *>::iterator iter = dieren->begin(); iter != dieren->end(); ++iter) {
		cout << "Diernummer: " << iter->first << endl;
		iter->second->drukaf();
	}
	cout << endl;
}



string Dierentuin::toString() {
	stringstream stringstr;
	stringstr << "Naam: " << de_naam;
	return stringstr.str();
}

ostream& operator<<(ostream& out, Dierentuin* w) {
	out << w->toString();

	return out;
}

void  Dierentuin::getBeschikbareBonnen(){
	BOND->printHuidigeBonnen();
}
void  Dierentuin::leverBonIn(){
	int i = 0;
	cout << "geef een bonnummer op dat ingeleverd moet worden" << endl;
	cin >> i;
	BOND->verwijderbon(i);
}

void Dierentuin::maakBonnen(){
	int i = 0;
	cout << "geef het aantal bonnen op dat er gemaakt moet worden." << endl;
	cin >> i;
	BOND->maakBonnen(i);
}

Singleton* Dierentuin::getBond(){
return BOND;
}

void Dierentuin::getSalarisPost(){
	p2f = &WerknemerAdmin::printSalarisPost;

	(objWA.*p2f)();
}

